from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm, OAuth2PasswordBearer
from typing import Optional, Dict, Any
from datetime import datetime, timedelta
import jwt
from ..utils.crypt_utils import verify_password, get_password_hash
from pydantic import BaseModel
import os
from ..utils.response_utils import success_response, error_response, create_response
from ..database.mongodb import database

router = APIRouter()

# 设置用于JWT的密钥和算法
SECRET_KEY = os.getenv("SECRET_KEY", "YOUR_SECRET_KEY_HERE")
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 60 * 24  # 24小时

# 创建用户集合
users_collection = database.get_collection("users")

# 用户模型
class User(BaseModel):
    username: str
    email: Optional[str] = None
    full_name: Optional[str] = None
    disabled: Optional[bool] = None
    password: str

# Token模型
class Token(BaseModel):
    access_token: str
    token_type: str

class TokenData(BaseModel):
    username: Optional[str] = None

# OAuth2 密码授权 - 修改为使用正确的API路径
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/token")

# 初始化默认用户函数
async def init_default_users():
    # 检查users集合是否存在用户
    user_count = await users_collection.count_documents({})
    
    if user_count == 0:
        # 如果没有用户，添加默认管理员和普通用户
        default_users = [
            {
                "username": "admin",
                "full_name": "Admin User",
                "email": "admin@example.com",
                "password": get_password_hash("admin123"),
                "disabled": False,
                "role": "admin",
                "created_at": datetime.utcnow()
            },
            {
                "username": "user",
                "full_name": "Normal User",
                "email": "user@example.com",
                "password": get_password_hash("user123"),
                "disabled": False,
                "role": "user",
                "created_at": datetime.utcnow()
            }
        ]
        # 插入默认用户到数据库
        await users_collection.insert_many(default_users)
        print("已创建默认用户")

# 从数据库中获取用户
async def get_user(username: str):
    user_dict = await users_collection.find_one({"username": username})
    if user_dict:
        return User(**user_dict)
    return None

# 验证用户凭证
async def authenticate_user(username: str, password: str):
    try:
        # 创建UserInDB实例进行验证
        user = await get_user(username)
        if not user:
            return False
        if not verify_password(password,user.password):
            return False
        return user
    except Exception as e:
        print(f"身份验证过程中发生错误: {str(e)}")
        return False

# 创建访问令牌
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
    to_encode = data.copy()
    expire = datetime.utcnow() + (expires_delta if expires_delta else timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES))
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

# 令牌验证
async def get_current_user(token: str = Depends(oauth2_scheme)):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="无效的认证凭证",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
        token_data = TokenData(username=username)
    except jwt.PyJWTError:
        raise credentials_exception
    
    user = await get_user(username=token_data.username)
    if user is None:
        raise credentials_exception
    return user

# 获取当前活跃用户
async def get_current_active_user(current_user: User = Depends(get_current_user)):
    user_dict = await users_collection.find_one({"username": current_user.username})
    if user_dict and user_dict.get("disabled", False):
        raise HTTPException(status_code=400, detail="用户已禁用")
    return current_user

# 登录路由
@router.post("/token")
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
    try:
        # 确保有默认用户
        await init_default_users()
        
        # 验证用户
        user = await authenticate_user(form_data.username, form_data.password)
        if not user:
            return error_response(message="用户名或密码错误", code=401)
        
        # 获取完整用户信息
        user_dict = await users_collection.find_one({"username": user.username})
        if not user_dict:
            return error_response(message="获取用户信息失败", code=500)
        
        # 创建访问令牌
        access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
        access_token = create_access_token(
            data={
                "sub": user.username, 
                "username": user.username, 
                "role": user_dict.get("role", "user")
            },
            expires_delta=access_token_expires
        )
        
        # 返回令牌
        return create_response(
            data={
                "access_token": access_token,
                "token_type": "bearer"
            },
            message="登录成功",
            code=200
        )
    except Exception as e:
        print(f"登录过程中发生错误: {str(e)}")
        return error_response(message=f"登录失败: {str(e)}", code=500)

# 获取当前用户信息
@router.get("/me")
async def read_users_me(current_user: User = Depends(get_current_active_user)):
    try:
        # 从数据库中获取最新的用户信息
        user_dict = await users_collection.find_one({"username": current_user.username})
        if not user_dict:
            return error_response(message="获取用户信息失败", code=404)
        
        # 过滤掉敏感信息
        user_info = {
            "username": user_dict["username"],
            "email": user_dict.get("email"),
            "full_name": user_dict.get("full_name"),
            "role": user_dict.get("role", "user")
        }
        
        return success_response(
            data=user_info,
            message="获取用户信息成功"
        )
    except Exception as e:
        print(f"获取用户信息过程中发生错误: {str(e)}")
        return error_response(message=f"获取用户信息失败: {str(e)}", code=500)

# 用户管理路由 - 只有管理员可以访问

# 获取所有用户
@router.get("/users")
async def get_all_users(current_user: User = Depends(get_current_active_user)):
    try:
        # 检查权限
        user_dict = await users_collection.find_one({"username": current_user.username})
        if not user_dict or user_dict.get("role") != "admin":
            return error_response(message="权限不足", code=403)
        
        # 获取所有用户
        users_cursor = users_collection.find({}, {
            "_id": 1,
            "username": 1, 
            "email": 1, 
            "full_name": 1, 
            "role": 1, 
            "disabled": 1,
            "created_at": 1
        })
        
        users_list = []
        async for user in users_cursor:
            # 将ObjectId转为字符串
            user["_id"] = str(user["_id"])
            users_list.append(user)
        
        return success_response(
            data=users_list,
            message="获取用户列表成功"
        )
    except Exception as e:
        print(f"获取用户列表过程中发生错误: {str(e)}")
        return error_response(message=f"获取用户列表失败: {str(e)}", code=500)

# 添加用户路由
@router.post("/users")
async def create_user(
    user_data: dict,
    current_user: User = Depends(get_current_active_user)
):
    try:
        # 检查权限
        admin_user = await users_collection.find_one({"username": current_user.username})
        if not admin_user or admin_user.get("role") != "admin":
            return error_response(message="权限不足", code=403)
        
        # 检查是否存在同名用户
        existing_user = await users_collection.find_one({"username": user_data["username"]})
        if existing_user:
            return error_response(message=f"用户名 {user_data['username']} 已存在", code=400)
        
        # 创建新用户
        new_user = {
            "username": user_data["username"],
            "full_name": user_data.get("full_name", ""),
            "email": user_data.get("email", ""),
            "password": get_password_hash(user_data["password"]),
            "disabled": user_data.get("disabled", False),
            "role": user_data.get("role", "user"),
            "created_at": datetime.utcnow()
        }
        
        # 插入到数据库
        result = await users_collection.insert_one(new_user)
        
        return success_response(
            data={"id": str(result.inserted_id)},
            message="用户创建成功"
        )
    except KeyError as e:
        return error_response(message=f"缺少必要字段: {str(e)}", code=400)
    except Exception as e:
        print(f"创建用户过程中发生错误: {str(e)}")
        return error_response(message=f"创建用户失败: {str(e)}", code=500)

# 更新用户路由
@router.put("/users/{user_id}")
async def update_user(
    user_id: str,
    user_data: dict,
    current_user: User = Depends(get_current_active_user)
):
    try:
        # 检查权限
        admin_user = await users_collection.find_one({"username": current_user.username})
        if not admin_user or admin_user.get("role") != "admin":
            return error_response(message="权限不足", code=403)
        
        # 查找用户
        from bson.objectid import ObjectId
        existing_user = await users_collection.find_one({"_id": ObjectId(user_id)})
        if not existing_user:
            return error_response(message=f"未找到ID为 {user_id} 的用户", code=404)
        
        # 准备更新数据
        update_data = {}
        if "full_name" in user_data:
            update_data["full_name"] = user_data["full_name"]
        if "email" in user_data:
            update_data["email"] = user_data["email"]
        if "role" in user_data:
            update_data["role"] = user_data["role"]
        if "disabled" in user_data:
            update_data["disabled"] = user_data["disabled"]
        if "password" in user_data:
            update_data["password"] = get_password_hash(user_data["password"])
        
        # 如果没有可更新的数据
        if not update_data:
            return error_response(message="没有提供要更新的数据", code=400)
        
        # 更新用户
        result = await users_collection.update_one(
            {"_id": ObjectId(user_id)},
            {"$set": update_data}
        )
        
        if result.modified_count == 0:
            return error_response(message="未修改任何数据", code=400)
        
        return success_response(
            message="用户信息更新成功"
        )
    except Exception as e:
        print(f"更新用户过程中发生错误: {str(e)}")
        return error_response(message=f"更新用户失败: {str(e)}", code=500)

# 删除用户路由
@router.delete("/users/{user_id}")
async def delete_user(
    user_id: str,
    current_user: User = Depends(get_current_active_user)
):
    try:
        # 检查权限
        admin_user = await users_collection.find_one({"username": current_user.username})
        if not admin_user or admin_user.get("role") != "admin":
            return error_response(message="权限不足", code=403)
        
        # 不允许删除自己
        from bson.objectid import ObjectId
        user_to_delete = await users_collection.find_one({"_id": ObjectId(user_id)})
        
        if not user_to_delete:
            return error_response(message=f"未找到ID为 {user_id} 的用户", code=404)
        
        if user_to_delete["username"] == current_user.username:
            return error_response(message="不能删除当前登录的用户", code=400)
        
        # 删除用户
        result = await users_collection.delete_one({"_id": ObjectId(user_id)})
        
        if result.deleted_count == 0:
            return error_response(message="未删除任何用户", code=400)
        
        return success_response(
            message="用户删除成功"
        )
    except Exception as e:
        print(f"删除用户过程中发生错误: {str(e)}")
        return error_response(message=f"删除用户失败: {str(e)}", code=500)

# 修改密码路由
@router.post("/change-password")
async def change_password(
    password_data: dict,
    current_user: User = Depends(get_current_active_user)
):
    try:
        # 验证旧密码
        user = await users_collection.find_one({"username": current_user.username})
        if not user:
            return error_response(message="用户不存在", code=404)
        
        if not verify_password(password_data["old_password"], user["password"]):
            return error_response(message="原密码不正确", code=400)
        
        # 更新密码
        new_hashed_password = get_password_hash(password_data["new_password"])
        result = await users_collection.update_one(
            {"username": current_user.username},
            {"$set": {"password": new_hashed_password}}
        )
        
        if result.modified_count == 0:
            return error_response(message="密码更新失败", code=500)
        
        return success_response(
            message="密码更新成功"
        )
    except KeyError as e:
        return error_response(message=f"缺少必要字段: {str(e)}", code=400)
    except Exception as e:
        print(f"修改密码过程中发生错误: {str(e)}")
        return error_response(message=f"修改密码失败: {str(e)}", code=500)